package com.authine.cloudpivot.ext.service.impl;

import com.alibaba.cola.dto.SingleResponse;
import com.authine.cloudpivot.ext.applicationservice.base.ApplicationBaseService;
import com.authine.cloudpivot.ext.constants.ModelConst;
import com.authine.cloudpivot.ext.constants.PlatformConst;
import com.authine.cloudpivot.ext.dto.transfer.ResaleInvoiceDetailDto;
import com.authine.cloudpivot.ext.dto.transfer.ResaleInvoiceDto;
import com.authine.cloudpivot.ext.dto.transfer.TransferOrderDto;
import com.authine.cloudpivot.ext.dto.transfer.TransferOrderGoodsDto;
import com.authine.cloudpivot.ext.enums.order.transfer.InvoiceStatus;
import com.authine.cloudpivot.ext.enums.order.transfer.OrderType;
import com.authine.cloudpivot.ext.service.PurchaseSaleService;
import com.authine.cloudpivot.ext.utils.BigDecimalUtils;
import com.authine.cloudpivot.ext.utils.BoServiceUtils;
import com.authine.cloudpivot.ext.utils.JdbcTemplateUtils;
import com.authine.cloudpivot.ext.utils.RegexUtils;
import com.authine.mvp.app.launcher.dto.bo.response.BO;
import com.authine.mvp.app.org.dto.domainmodel.UnitType;

import java.math.BigDecimal;
import java.util.*;

public class PurchaseSaleServiceImpl extends ApplicationBaseService implements PurchaseSaleService {

    /**
     * @parem transferOrder 转售订单保存
     * cn/gomro/core/bizes/purchase/management/service/impl/PurchaseReSaleService.saveOutputOrder
     */
    @Override
    public SingleResponse<BO> saveOutputOrder(TransferOrderDto transferOrder) throws RuntimeException {
        //验证订单信息
        checkOutputOrderInfo(transferOrder);
        if (null == transferOrder) {
            throw new RuntimeException("订单信息不能为空");
        }
        Map<String, Object> saveTransferOrder = TransferOrderDto.voToEntity(transferOrder);
        saveTransferOrder.put("order_type", OrderType.Sale.name());
        //订单总和含税
        Double orderTotal = transferOrder.getTransferOrderGoods().stream().filter(t -> null != t.getTotal()).mapToDouble(t -> t.getTotal().doubleValue()).sum();
        saveTransferOrder.put("total", orderTotal);
        Double orderPreTotal = transferOrder.getTransferOrderGoods().stream().filter(t -> null != t.getPre_total()).mapToDouble(t -> t.getPre_total().doubleValue()).sum();
        saveTransferOrder.put("pre_total", orderPreTotal);
        Double orderAmount = transferOrder.getTransferOrderGoods().stream().filter(t -> null != t.getAmount()).mapToDouble(t -> t.getAmount().doubleValue()).sum();
        saveTransferOrder.put("amount", orderAmount);
        Double orderPreAmount = transferOrder.getTransferOrderGoods().stream().filter(t -> null != t.getPre_amount()).mapToDouble(t -> t.getPre_amount().doubleValue()).sum();
        saveTransferOrder.put("pre_amount", orderPreAmount);
        
        SingleResponse<BO> transferOrderResult = BoServiceUtils.createBo(ModelConst.T_TRANSFER_ORDER, Collections.singletonList(saveTransferOrder));
        List<Map<String, Object>> transferOrderGoods = saveOutputOrderGoods(transferOrder);
        for (Map<String, Object> transferOrderGood : transferOrderGoods) {
            transferOrderGood.put("transfer_order_id", transferOrderResult.getData().getBizObjectId());
        }
        BoServiceUtils.createBo(ModelConst.T_TRANSFER_ORDER_GOODS, transferOrderGoods);
        if (!transferOrderResult.isSuccess()) {
            throw new RuntimeException("转售订单保存失败！");
        }
        //保存转售记录
        saveSalesRecord(transferOrderResult.getData().getData());
        return transferOrderResult;
    }

    /**
     * 保存转售订单商品
     */
    public List<Map<String, Object>> saveOutputOrderGoods(TransferOrderDto transferOrder) throws RuntimeException {
        List<Map<String, Object>> saveTransferOrderGoods = new ArrayList<>();
        for (TransferOrderGoodsDto transferOrderGoods : transferOrder.getTransferOrderGoods()) {
            BigDecimal saleRecordNum = BigDecimal.ZERO;
            BigDecimal saleRNum = this.getSaleRecordNum(transferOrderGoods.getCloud_order_goods_id());
            if (null != saleRNum) {
                saleRecordNum = saleRNum;
            }
            BigDecimal outPutNum = BigDecimalUtils.add(saleRecordNum, transferOrderGoods.getNum());
            BigDecimal saleNum = BigDecimalUtils.isNull(transferOrderGoods.getSale_num());
            if (outPutNum.compareTo(saleNum) == 1) {
                throw new RuntimeException("出库数量不能大于销售数量");
            }
            Map<String, Object> newTransferOrderGoods = TransferOrderGoodsDto.voToEntity(transferOrderGoods);
            newTransferOrderGoods.put("order_type", OrderType.Sale.name());
            newTransferOrderGoods.put("purchase_batch", 0);
            newTransferOrderGoods.put("apply_num", 0.0);
            newTransferOrderGoods.put("apply_amount", 0.0);
            newTransferOrderGoods.put("not_purchase", false);
            newTransferOrderGoods.put("quantity_purchased", 0.00);
            BigDecimal price = BigDecimalUtils.round(BigDecimalUtils.mul(transferOrderGoods.getPre_price(),
                    BigDecimalUtils.add(transferOrderGoods.getTax_rate(), BigDecimal.ONE)), 16);
            newTransferOrderGoods.put("price", price);
            BigDecimal total = BigDecimalUtils.mul(BigDecimalUtils.mul(transferOrderGoods.getPre_price(), BigDecimalUtils.add(transferOrderGoods.getTax_rate(), BigDecimal.ONE)), transferOrderGoods.getNum());
            newTransferOrderGoods.put("total", BigDecimalUtils.round(total, 2));
            BigDecimal preTotal = BigDecimalUtils.mul(transferOrderGoods.getPre_price(), transferOrderGoods.getNum());
            newTransferOrderGoods.put("pre_total", BigDecimalUtils.round(preTotal, 2));
            newTransferOrderGoods.put("amount", BigDecimalUtils.round(BigDecimalUtils.add(total, transferOrderGoods.getFreight()), 2));
            newTransferOrderGoods.put("pre_amount", BigDecimalUtils.round(BigDecimalUtils.add(preTotal, transferOrderGoods.getFreight()), 2));
            saveTransferOrderGoods.add(newTransferOrderGoods);

        }
        return saveTransferOrderGoods;
    }

    /**
     * 验证出库单信息
     *
     * @param transferOrder
     */
    public static void checkOutputOrderInfo(TransferOrderDto transferOrder) {
        if (null == transferOrder.getMember_id()) {
            throw new RuntimeException("客户不能为空");
        }
        if (!RegexUtils.notNull(transferOrder.getAddress())) {
            throw new RuntimeException("电话不能为空");
        }
        if (!RegexUtils.notNull(transferOrder.getPhone())) {
            throw new RuntimeException("收货地址不能为空");
        }
        if (null == transferOrder.getReceiver()) {
            throw new RuntimeException("收货人不能为空");
        }
        for (TransferOrderGoodsDto goods : transferOrder.getTransferOrderGoods()) {
            if (null == goods.getPrice()) {
                throw new RuntimeException("出库单价不能为空");
            }
            if (null == goods.getNum()) {
                throw new RuntimeException("出库数量不能为空");
            }
        }
    }

    /**
     * 获取转售流水转售数量
     *
     * @param cloudOrderGoodsId
     * @return
     */
    public BigDecimal getSaleRecordNum(String cloudOrderGoodsId) {
        BigDecimal sumNum = JdbcTemplateUtils.builder(ModelConst.T_SALES_RECORD).selectField("sum(num)")
                .eq("cloud_order_goods_id", cloudOrderGoodsId).queryForObject(BigDecimal.class);
        return sumNum;
    }

    /**
     * 保存转售记录
     *
     * @param transferOrder
     * @return
     */
    private void saveSalesRecord(Map<String, Object> transferOrder) {
        List<Map<String, Object>> salesRecordEntities = new ArrayList<>();
        List<Map<String, Object>> transferOrderGoods = JdbcTemplateUtils.builder(ModelConst.T_TRANSFER_ORDER_GOODS)
                .selectField("*").eq("transfer_order_id", transferOrder.get("id")).queryForList();
        transferOrderGoods.forEach(goods -> {
            Map<String, Object> salesRecordEntity = new HashMap<>();
            salesRecordEntity.put("cloud_order_id", transferOrder.get("cloud_order_id"));
            salesRecordEntity.put("transfer_order_id", transferOrder.get("id"));
            salesRecordEntity.put("cloud_order_goods_id", goods.get("cloud_order_goods_id"));
            salesRecordEntity.put("transfer_order_goods_id", goods.get("id"));
            salesRecordEntity.put("num", goods.get("num"));
            salesRecordEntity.put("tax_rate", BigDecimalUtils.round(BigDecimalUtils.isNull(goods.get("tax_rate")), 2));
            salesRecordEntity.put("price", goods.get("price"));
            salesRecordEntity.put("pre_price", goods.get("pre_price"));
            salesRecordEntity.put("total", BigDecimalUtils.round(BigDecimalUtils.isNull(goods.get("total")), 2));
            salesRecordEntity.put("pre_total", BigDecimalUtils.round(BigDecimalUtils.isNull(goods.get("pre_total")), 2));
            salesRecordEntity.put("pre_amount", BigDecimalUtils.round(BigDecimalUtils.isNull(goods.get("pre_amount")), 2));
            salesRecordEntity.put("amount", BigDecimalUtils.round(BigDecimalUtils.isNull(goods.get("amount")), 2));
            salesRecordEntities.add(salesRecordEntity);
        });
        SingleResponse<BO> response = BoServiceUtils.createBo(ModelConst.T_SALES_RECORD, salesRecordEntities);
        if (!response.isSuccess()) {
            throw new RuntimeException("转售记录保存失败");
        }
    }

    /**
     * 确认开票
     * cn/gomro/core/bizes/purchase/management/service/impl/PurchaseReSaleService.confirmResaleInvoice
     *
     * @param resaleInvoiceModel
     * @return
     */
    @Override
    public SingleResponse<BO> confirmResaleInvoice(ResaleInvoiceDto resaleInvoiceModel) {
        checkConfirmInvoice(resaleInvoiceModel);
        Map<String, Object> one = JdbcTemplateUtils.builder(ModelConst.T_RESALE_INVOICE).selectField("*").eq("id", resaleInvoiceModel.getId()).queryForMap();
        if (!one.get("resale_invoice_status").equals(InvoiceStatus.DrawerConfirming.name())) {
            throw new RuntimeException("请选择待开票状态进行确认");
        }
        Map<String, Object> resaleInvoiceParam = new HashMap<>();
        resaleInvoiceParam.put("id", one.get("id"));
        resaleInvoiceParam.put("date", resaleInvoiceModel.getDate());
        resaleInvoiceParam.put("code", resaleInvoiceModel.getCode());
        resaleInvoiceParam.put("number", resaleInvoiceModel.getNumber());
        resaleInvoiceParam.put("drawer", resaleInvoiceModel.getDrawer());
        resaleInvoiceParam.put("resale_invoice_status", InvoiceStatus.Done.name());
        return BoServiceUtils.updateMainBo(ModelConst.T_RESALE_INVOICE, resaleInvoiceParam);
    }

    /**
     * 确认开票 model验证
     */
    public static void checkConfirmInvoice(ResaleInvoiceDto resaleInvoiceModel) {
        if (null == resaleInvoiceModel.getId()) {
            throw new RuntimeException("id不能为空");
        }
        if (null == resaleInvoiceModel.getDate()) {
            throw new RuntimeException("确认日期不能为空");
        }
        if (null == resaleInvoiceModel.getCode()) {
            throw new RuntimeException("发票代码不能为空");
        }
        if (null == resaleInvoiceModel.getNumber()) {
            throw new RuntimeException("发票号码不能为空");
        }
        if (null == resaleInvoiceModel.getDrawer()) {
            throw new RuntimeException("开票人不能为空");
        }
    }

    /**
     * 保存转售发票信息
     *
     * @param resaleInvoiceModel
     * @return
     */
    @Override
    public SingleResponse<BO> saveResaleInvoice(ResaleInvoiceDto resaleInvoiceModel) throws RuntimeException {
        //检查信息发票
        checkInvoiceInfo(resaleInvoiceModel);

        Map<String, Object> newResaleInvoice = new HashMap<>();
        newResaleInvoice.put("type", resaleInvoiceModel.getType());
        newResaleInvoice.put("purchase_name", resaleInvoiceModel.getPurchase_name());
        newResaleInvoice.put("purchase_bank", resaleInvoiceModel.getPurchase_bank());
        newResaleInvoice.put("purchase_account", resaleInvoiceModel.getPurchase_account());
        newResaleInvoice.put("purchase_address", resaleInvoiceModel.getPurchase_address());
        newResaleInvoice.put("purchase_phone", resaleInvoiceModel.getPurchase_phone());
        newResaleInvoice.put("purchase_number", resaleInvoiceModel.getPurchase_number());
        newResaleInvoice.put("receiver", resaleInvoiceModel.getReceiver());
        newResaleInvoice.put("address", resaleInvoiceModel.getAddress());
        newResaleInvoice.put("phone", resaleInvoiceModel.getPhone());
        newResaleInvoice.put("memo", resaleInvoiceModel.getMemo());
        newResaleInvoice.put("apply_member_id", getSelectorFormat());
        newResaleInvoice.put("apply_member_name", getSelectorFormat().getName());
        newResaleInvoice.put("purchase_organization_id", getSelectorFormat(null, UnitType.DEPARTMENT));
        newResaleInvoice.put("purchase_organization_name", getSelectorFormat(null, UnitType.DEPARTMENT).getName());
//        newResaleInvoice.put("confirm_organization_id", PlatformConst.ORGANIZATIONID);
        newResaleInvoice.put("confirm_organization_id", resaleInvoiceModel.getConfirm_organization_id());
        newResaleInvoice.put("confirm_organization_name", PlatformConst.ORGANIZATION_NAME);
        newResaleInvoice.put("resale_invoice_status", InvoiceStatus.DrawerConfirming.name());
        newResaleInvoice.put("apply_time", new Date());
//        Long goldenTaxId = goldenTaxApi.sequenceGoldenTaxId().getData();
//        if (null == goldenTaxId) {
//            throw new RuntimeException("金税发票单ID不能为空！");
//        }

        List<Map<String, Object>> resaleInvoiceDetailEntities = new ArrayList<>();
        HashMap<String, BigDecimal> invoiceInfo = new HashMap<>();
        //构建发票明细
        for (ResaleInvoiceDetailDto detail : resaleInvoiceModel.getResaleInvoiceDetails()) {
            //含税总计
            BigDecimal amount = BigDecimalUtils.round(BigDecimalUtils.mul(detail.getPrice(), detail.getQuantity()), 2);
            //未税总计
            BigDecimal total = BigDecimalUtils.round(BigDecimalUtils.mul(detail.getPretax_price(), detail.getQuantity()), 2);
            //税额
            BigDecimal tax = BigDecimalUtils.sub(amount, total);
            //构建发票明细数据
            Map<String, Object> newInvoiceDetail = new HashMap<>();
            newInvoiceDetail.put("goods_id", detail.getGoods_id());
            newInvoiceDetail.put("amount", amount);
            newInvoiceDetail.put("total", total);
            newInvoiceDetail.put("tax", tax);
            newInvoiceDetail.put("name", detail.getName());
            newInvoiceDetail.put("quantity", detail.getQuantity());
            newInvoiceDetail.put("model_spec", detail.getModel_spec());
            newInvoiceDetail.put("price", detail.getPrice());
            newInvoiceDetail.put("pretax_price", detail.getPretax_price());
            newInvoiceDetail.put("tax_rate", detail.getTax_rate());
            newInvoiceDetail.put("unit", detail.getUnit());
            newInvoiceDetail.put("golden_tax", detail.getGolden_tax());
            //构建发票map  用于回写订单商品开票数量
            invoiceInfo.put(detail.getGoods_id(), detail.getQuantity());
            resaleInvoiceDetailEntities.add(newInvoiceDetail);
        }

        //税额总计
        double taxAmount = resaleInvoiceDetailEntities.stream().filter(t -> null != t.get("tax")).mapToDouble(t -> BigDecimalUtils.isNull(t.get("tax")).doubleValue()).sum();
        //含税总计
        double priceAmount = resaleInvoiceDetailEntities.stream().filter(t -> null != t.get("amount")).mapToDouble(t -> BigDecimalUtils.isNull(t.get("amount")).doubleValue()).sum();
        //未税总计
        double invoiceTotal = resaleInvoiceDetailEntities.stream().filter(t -> null != t.get("total")).mapToDouble(t -> BigDecimalUtils.isNull(t.get("total")).doubleValue()).sum();

        newResaleInvoice.put("tax_amount", taxAmount);
        newResaleInvoice.put("price_amount", priceAmount);
        newResaleInvoice.put("total", invoiceTotal);

        SingleResponse<BO> save = BoServiceUtils.createBo(ModelConst.T_RESALE_INVOICE, Collections.singletonList(newResaleInvoice));
        if (!save.isSuccess()) {
            throw new RuntimeException("发票申请单保存失败！");
        }
        resaleInvoiceDetailEntities.stream().forEach(t -> t.put("resale_invoice_id", save.getData().getBizObjectId()));
        BoServiceUtils.createBo(ModelConst.T_RESALE_INVOICE_DETAIL, resaleInvoiceDetailEntities);

        //回写订单商品表开票数据
        this.updateInvoiceApplyNumAndAmount(invoiceInfo);
        //保存金税表数据
//        this.creatGoldenTax(save.getData().getData());
        return save;
    }

    /**
     * 检查发票
     *
     * @param resaleInvoiceModel
     */
    public static void checkInvoiceInfo(ResaleInvoiceDto resaleInvoiceModel) {

        if (null == resaleInvoiceModel.getType()) {
            throw new RuntimeException("票据类型不能为空");

        }
        if (!RegexUtils.notNull(resaleInvoiceModel.getPurchase_name())) {
            throw new RuntimeException("发票抬头不能为空");
        }
        if (!RegexUtils.notNull(resaleInvoiceModel.getPurchase_address())) {
            throw new RuntimeException("开票地址不能为空");

        }
        if (!RegexUtils.notNull(resaleInvoiceModel.getPurchase_phone())) {
            throw new RuntimeException("电话不能为空");

        }
        if (!RegexUtils.notNull(resaleInvoiceModel.getPurchase_bank())) {
            throw new RuntimeException("开户行不能为空");

        }
        if (!RegexUtils.notNull(resaleInvoiceModel.getPurchase_account())) {
            throw new RuntimeException("账号不能为空");

        }
        if (!RegexUtils.notNull(resaleInvoiceModel.getPurchase_number())) {
            throw new RuntimeException("税号不能为空");

        }
        if (!RegexUtils.notNull(resaleInvoiceModel.getAddress())) {
            throw new RuntimeException("收票地址不能为空");

        }
        if (!RegexUtils.notNull(resaleInvoiceModel.getReceiver())) {
            throw new RuntimeException("收票人名称不能为空");

        }
        if (!RegexUtils.notNull(resaleInvoiceModel.getPhone())) {
            throw new RuntimeException("收票人电话不能为空");

        }
        for (ResaleInvoiceDetailDto detail : resaleInvoiceModel.getResaleInvoiceDetails()) {
            if (null == detail.getQuantity()) {
                throw new RuntimeException("申请数量不能为空");
            }
        }
    }

    /**
     * 回写订单商品表开票数据
     *
     * @param invoiceInfo
     */
    public void updateInvoiceApplyNumAndAmount(HashMap<String, BigDecimal> invoiceInfo) {
        List<Map<String, Object>> transferOrderGoodsParams = new ArrayList<>();
        for (Map.Entry<String, BigDecimal> entry : invoiceInfo.entrySet()) {
            Map<String, Object> transferOrderGoodsEntity = JdbcTemplateUtils.builder(ModelConst.T_TRANSFER_ORDER_GOODS)
                    .selectField("*").eq("id", entry.getKey()).queryForMap();
            BigDecimal applyNum = BigDecimalUtils.add(entry.getValue(), BigDecimalUtils.isNull(transferOrderGoodsEntity.get("apply_num")));
            if (applyNum.compareTo(BigDecimalUtils.isNull(transferOrderGoodsEntity.get("num"))) == 1) {
                throw new RuntimeException("订单商品：" + transferOrderGoodsEntity.get("id") + "申请数量不能大于订单数量");
            }
            Map<String, Object> transferOrderGoodsParam = new HashMap<>();
            transferOrderGoodsParam.put("id", transferOrderGoodsEntity.get("id"));
            transferOrderGoodsParam.put("apply_amount", BigDecimalUtils.round(BigDecimalUtils.mul(applyNum, BigDecimalUtils.isNull(transferOrderGoodsEntity.get("price"))), 2));
            transferOrderGoodsParam.put("apply_num", applyNum.toPlainString());
            transferOrderGoodsParams.add(transferOrderGoodsParam);
        }
        SingleResponse<BO> response = BoServiceUtils.updateMainBo(ModelConst.T_TRANSFER_ORDER_GOODS, transferOrderGoodsParams);
        if (!response.isSuccess()) {
            throw new RuntimeException("订单商品开票数量回写失败");
        }
    }
}
